﻿#include "datafiledst.h"


DataFileDst::DataFileDst()
{
}

DataFileDst::~DataFileDst()
{
}

void DataFileDst::clear()
{
    m_fileFullPathName.clear(); // 文件路径
    m_fileData.clear();         // 文件数据内容
    m_embAbsData.clear();          // 转换后的数据
}

void DataFileDst::initFile(const QString &fullPathName)
{
    clear();
    QFileInfo file(fullPathName);
    if (file.exists() && file.isFile())
    {
        m_fileFullPathName = fullPathName;
        m_fileName = fullPathName;
        qDebug()<<"m_fileFullPathName 1"<<m_fileFullPathName;
    }
    else
    {
        qDebug() << "Init file failed path =" << m_fileFullPathName;
    }
}

void DataFileDst::loadFile()
{
    QFile rdfile(m_fileFullPathName);
    if(!rdfile.open(QIODevice::ReadOnly))
    {
        qDebug() << "open file fail when read, path =" << m_fileFullPathName;
        return;
    }

    m_fileData = rdfile.readAll();

    rdfile.close();

    return;
}

void DataFileDst::saveFile()
{
    QFile wrfile(m_fileFullPathName);
    if(!wrfile.open(QIODevice::WriteOnly | QIODevice::Truncate))
    {
        qDebug() << "open file fail when wirte, path =" << m_fileFullPathName;
        return;
    }
    else
    {
        wrfile.write(m_fileData);
        wrfile.close();
    }

    return;
}

// 文件所在目录
QString DataFileDst::getFileFullPath()
{
    QFileInfo file(m_fileFullPathName);
    return file.absoluteFilePath();
}

// 文件名称（包括扩展名）
QString DataFileDst::getFileFullName()
{
    QFileInfo file(m_fileFullPathName);
    return file.fileName();
}

// 文件名称（不包括扩展名）
QString DataFileDst::getFileName()
{
    QFileInfo file(m_fileFullPathName);
    return file.completeBaseName();
}

// 文件扩展名
QString DataFileDst::getFileSuffix()
{
    QFileInfo file(m_fileFullPathName);
    return file.suffix();
}

int DataFileDst::getStitchNums()
{
    if(m_embAbsData.size() <= 0)
    {
        return 0;
    }

    DataDs16FileHead * pDstHead = (DataDs16FileHead *)((m_embAbsData.data()));
    return pDstHead->itemNums;
}

int DataFileDst::getDatWidth()
{
    if(m_embAbsData.size() <= 0)
    {
        return 0;
    }

    DataDs16FileHead * pDstHead = (DataDs16FileHead *)((m_embAbsData.data()));
    return (pDstHead->maxX - pDstHead->minX);
}

int DataFileDst::getDatHeight()
{
    if(m_embAbsData.size() <= 0)
    {
        return 0;
    }

    DataDs16FileHead * pDstHead = (DataDs16FileHead *)((m_embAbsData.data()));
    return (pDstHead->maxY - pDstHead->minY);
}

int DataFileDst::getMaxX()
{
    if(m_embAbsData.size() <= 0)
    {
        return 0;
    }

    DataDs16FileHead * pDstHead = (DataDs16FileHead *)((m_embAbsData.data()));
    return pDstHead->maxX;
}

int DataFileDst::getMinX()
{
    if(m_embAbsData.size() <= 0)
    {
        return 0;
    }

    DataDs16FileHead * pDstHead = (DataDs16FileHead *)((m_embAbsData.data()));
    return pDstHead->minX;
}

int DataFileDst::getMaxY()
{
    if(m_embAbsData.size() <= 0)
    {
        return 0;
    }

    DataDs16FileHead * pDstHead = (DataDs16FileHead *)((m_embAbsData.data()));
    return pDstHead->maxY;
}

int DataFileDst::getMinY()
{
    if(m_embAbsData.size() <= 0)
    {
        return 0;
    }

    DataDs16FileHead * pDstHead = (DataDs16FileHead *)((m_embAbsData.data()));
    return pDstHead->minY;
}

int DataFileDst::getBeginXYAndAnchorXY(int &beginX, int &beginY, int &anchorX, int &anchorY)
{
    int size = m_fileData.size();
    if (size <= (int)(sizeof(DstHead)))
    {
        return -1;
    }

    DstHead * pDstHead = (DstHead *)((m_fileData.data()));
    beginX = pDstHead->startX;
    beginY = pDstHead->startY;
    anchorX = pDstHead->anchorX;
    anchorY = pDstHead->anchorY;

    return 0;
}

// 转换为绝对坐标数据，同时得到最大最小值
void DataFileDst::convertDataToAbs()
{
    QByteArray ds4Data;//相对坐标
    m_embAbsData.clear();
    loadFile();     // 如果数据未读取，重新读取

    int size = m_fileData.size();
    if (size <= (int)(sizeof(DstHead)))
    {
        qDebug("dst size less then headsize");
        return;
    }
    //    int dstHeadSize = sizeof(DstHead);
    //    qDebug()<<"dstHeadSize"<<dstHeadSize;

    size -= sizeof(DstHead);
    int stepsize = size/sizeof(DstStep);
    if (stepsize <= 0)
    {
        qDebug("dst data size err");
        return;
    }

    DstHead * dstHead = (DstHead *)(m_fileData.data());

    DstStep * dstDataBeg = (DstStep *)((m_fileData.data() + sizeof(DstHead)));
    DstStep * dstDataPtr = dstDataBeg;

    //qDebug()<<"Ds4Item begin";
    // 绝对坐标数据
    DataDs16FileHead dhead;
    memset(&dhead, 0, sizeof(DataDs16FileHead));

    Ds4Item * pData = new Ds4Item[stepsize];
    if (pData == NULL)
    {
        qDebug("new DsAbsItem failed, size=%d", stepsize);
        return;
    }

    Ds4Item ds4Item;
    u8 ctrl, attr;
    int dx, dy;
    int rslt;
    u32 jumpNeedleNum = 0;
    //int predr,curdr;
    //predr = curdr = 0.0;
    // 得到最大最小值, 同时转换为相对坐标数据
    int i = 0;
    int stepidx = 0;
    do
    {
        if (i < stepsize)
        {
            rslt = changeDstStep(dstDataPtr, ds4Item);//三字节针步转换
            if (rslt >= 0)
            {
                ctrl = ds4Item.ctrl;
                attr = ds4Item.attr;

                if ( ctrl == DATA_SEWING  ||
                     ctrl == DATA_OFFSET ||
                     0 )
                {
                    if(ctrl == DATA_OFFSET)
                    {
                        jumpNeedleNum++;
                    }

                    dx = ds4Item.dx * DATAFACTOR;
                    dy = ds4Item.dy * DATAFACTOR;

                    if ((attr & 0x80) != 0)
                    {
                        dx *= -1;
                    }
                    if ((attr & 0x40) != 0)
                    {
                        dy *= -1;
                    }
                }

                memcpy(&(pData[stepidx]), &ds4Item, sizeof(Ds4Item));
                stepidx++;
            }

            dstDataPtr++;
            i++;
        }
        else
        {
            break;
        }
    }while(1);

    //qDebug()<<"Ds4Item end";
    //再将相对坐标转换为绝对坐标---开始
    ds4Data.append((char *)pData, stepidx*sizeof(Ds4Item));//相对坐标字节数组
    u32 fileID = 0;
    fileID = calcCheckSum32((u8 *)(ds4Data.data()) , ds4Data.length());		// 原始数据累加校验和

    QByteArray absItemAry;
    absItemAry.clear();

    DsAbsItem absItem;
    memset(&absItem,0,sizeof(DsAbsItem));
    u8 ctrlByte;
    u8 attrByte;
    int ddx, ddy;

    m_maxX = S32_MIN;
    m_maxY = S32_MIN;
    m_minY = S32_MAX;
    m_minX = S32_MAX;

    Ds4Item * pDs4Data = (Ds4Item *)(ds4Data.data());
    Ds4Item * ds4DataPtr = pDs4Data;

    int begX = dstHead->startX;//起始点
    int begY = dstHead->startY;
    int begR = 0;
    int anchorX = dstHead->anchorX;//定位点
    int anchorY = dstHead->anchorY;

    s32 ax = 0;//第一个点
    s32 ay = 0;
    s32 ar = 0;

    Ds4Item * ds4DataTemp = (Ds4Item *)(ds4Data.data()); // ljs

    int ds4StepSize = ds4Data.size()/sizeof(Ds4Item);

    int runflag = 0;

    int delStepNum = 0; // ljs

    for (int i = 0; i < ds4StepSize; i++)
    {
        // 读入一个针步数据
        ctrlByte = ds4DataPtr->ctrl;
        attrByte = ds4DataPtr->attr;
        ddx = ds4DataPtr->dx * DATAFACTOR;
        ddy = ds4DataPtr->dy * DATAFACTOR;

        if ((attrByte & 0x80) != 0)
        {
            ddx *= -1;
        }
        if ((attrByte & 0x40) != 0)
        {
            ddy *= -1;
        }
        ddx *= DST_EMB_DATADIRX;
        ddy *= DST_EMB_DATADIRY;

        ax += ddx;
        ay += ddy;
        //ar = atan2(ddy,ddx) * 10000;
        double tar = atan2(ddy,ddx);
        ar = (tar * 10000+0.5*(tar>0?1:-1));

        if(ctrlByte == DATA_OFFSET)
        {
            if (runflag == 0)
            {
                runflag = 1;
            }
            runflag++;
        }
        else if(ctrlByte == DATA_SEWING)//第一针不转换为跳针
        {
            if ((runflag == 0 || runflag > 3) && (i > 0))   // 第一个运针是入针
            {
                ctrlByte = DATA_OFFSET;
                runflag = 1;
            }
            //else if (i == 0 && ddx == 0 && ddy == 0)   // 第一针，入针，向后扫描，如果有连续的三个跳针，则将第一针入针转换为跳针 ljs
            else if (i == 0)   // 20230511 第一针，入针，向后扫描，如果有连续的三个跳针，则将第一针入针转换为跳针 ljs
            {
                int count = 0;
                do
                {
                    ds4DataTemp++;
                    if (ds4DataTemp->ctrl == DATA_OFFSET)
                    {
                        count++;
                        if (ds4DataTemp->dx == 0 && ds4DataTemp->dy == 0)   // 空跳，直接变成跳针
                        {
                            count += 2;
                        }
                    }
                    else
                    {
                        break;
                    }
                }while(1);
                if  (count >= 3)
                {
                    ctrlByte = DATA_OFFSET;
                    runflag = 2;
                }
                else
                {
                    runflag = 1;
                }
            }
            else
            {
                runflag = 1;
            }
        }
        else if (ctrlByte == DATA_CHGND)    // 换色
        {
            runflag = 10;
        }
        else
        {
            runflag = 0;
        }

        //中间数据
        absItem.ctrl = ctrlByte;
        absItem.attr = attrByte & ~(0x80|0x40);
        absItem.ax = ax;
        absItem.ay = ay;
        absItem.ar = ar;

        if (ax > m_maxX)
        {
            m_maxX = ax;
        }
        if (ax < m_minX)
        {
            m_minX = ax;
        }
        if (ay > m_maxY)
        {
            m_maxY = ay;
        }
        if (ay < m_minY)
        {
            m_minY = ay;
        }

        absItemAry.append((char*)&absItem,sizeof(DsAbsItem));

        ds4DataPtr++;
    }

    //int newstepnum = ds4StepSize;    // 转换后的数据长度
    int newstepnum = ds4StepSize-delStepNum;    // 转换后的数据长度 ljs

    //qDebug()<<"DsAbsItem end";

    //再将相对坐标转换为绝对坐标---结束
    //qDebug()<<"dhead begin";
    // 文件头转换
    QString name = getFileFullName();
    int namelen = name.size();
    if (namelen > HEAD_NAME_STR_LEN)
    {
        namelen = HEAD_NAME_STR_LEN;
    }
    QByteArray array = name.toLocal8Bit().data();
    int asize = array.length();
    memcpy(dhead.fileName, array, asize);   // 文件名称
    dhead.dataSize = newstepnum*sizeof(DsAbsItem);   // 数据字节数
    dhead.itemNums = newstepnum;                    // 数据项个数
    dhead.bytesPerItem = sizeof(DsAbsItem);           // 每项占的字节数
    dhead.bytesPerBlk = MAX_EXDP_LEN;               // 数据内容划分块大小
    dhead.dataChecksum = calcCheckSum32((u8 *)(absItemAry.data()) , dhead.dataSize);		// 数据累加校验和
    dhead.checkCrc = calcCrc16((u8 *)(&dhead), HEAD_FIX_INFO_LEN);          // 前面6个字段的CRC校验，（6个字段分别为：文件名称，字节数，项个数，每项字节数，每块字节数，数据累加和的CRC校验值）
    dhead.fileid = fileID;
    //qDebug()<<"dhead 1";

    dhead.anchorX = anchorX;  // 定位点坐标X
    dhead.anchorY = anchorY;  // 定位点坐标Y
    dhead.beginX = begX;  // 数据起点坐标X
    dhead.beginY = begY;  // 数据起点坐标Y
    dhead.beginR = begR;                // 数据起点坐标R
    dhead.minX = m_minX-m_minX;
    dhead.maxX = m_maxX-m_minX;
    dhead.minY = m_minY-m_minY;
    dhead.maxY = m_maxY-m_minY;                // 轮廓范围，使用重新计算之后的值

    //qDebug()<<"m_maxX"<<m_maxX<<"m_minX"<<m_minX;
    //qDebug()<<"m_maxY"<<m_maxY<<"m_minY"<<m_minY;

    //qDebug()<<"dhead 3";
    // 保存文件头到数组中
    m_embAbsData.append((char *)(&dhead), sizeof(DataDs16FileHead));

    //qDebug()<<"dhead 4";
    // 保存数据到数组中
    //qDebug()<<"newstepnum"<<newstepnum;
    //qDebug()<<"ds4StepSize"<<ds4StepSize;

    m_embAbsData.append(absItemAry);
    delete []pData;

    //qDebug()<<"dhead end";

    return;
}

void DataFileDst::writePointToFile(int x, int y, int flag)
{
    if(m_fileData.size() <= 0)
    {
        return;
    }

    DstHead * pDstHead = (DstHead *)((m_fileData.data()));
    if(flag == 0)
    {
        pDstHead->startX = x;
        pDstHead->startY = y;
    }
    else
    {
        pDstHead->anchorX = x;
        pDstHead->anchorY = y;
    }
    QFile wfile(m_fileFullPathName);
    if(!wfile.open(QIODevice::WriteOnly | QIODevice::Truncate))
    {
        qDebug() << "open file fail when read, path =" << m_fileFullPathName;
        return;
    }

    wfile.write(m_fileData);
    wfile.close();
}

void DataFileDst::writePatternParaToFile(DstHead *head)
{
    if(m_fileData.size() <= 0)
    {
        return;
    }

    memcpy(m_fileData.data(),(char*)head,sizeof(DstHead));

    QFile wfile(m_fileFullPathName);
    if(!wfile.open(QIODevice::WriteOnly | QIODevice::Truncate))
    {
        qDebug() << "open file fail when read, path =" << m_fileFullPathName;
        return;
    }

    wfile.write(m_fileData);
    wfile.close();
}

int DataFileDst::checkDstFile()
{
    loadFile();     // 如果数据未读取，重新读取

    int size = m_fileData.size();
    if (size <= (int)(sizeof(DstHead)))
    {
        qDebug("dsr size less then headsize");
        return -1;
    }

    size -= sizeof(DstHead);
    int stepsize = size/sizeof(DstStep);
    if (stepsize <= 0)
    {
        qDebug("dst data size err");
        return -1;
    }

    if (stepsize > PATTERN_LARGE_NEEDLES)//128万针
    {
        qDebug("dsr data size big");
        return -2;
    }

    return stepsize;
}

DstHead *DataFileDst::getDstHead()
{
    if(m_fileData.size() <= 0)
    {
        loadFile();     // 如果数据未读取，重新读取
    }
    DstHead *head = NULL;

    int size = m_fileData.size();
    if (size <= (int)(sizeof(DstHead)))
    {
        return head;
    }

    head = (DstHead *)((m_fileData.data()));
    return head;
}

void DataFileDst::moveDataBeginPonit(s32 left, s32 front)
{
    if((u32)m_embAbsData.size() > sizeof(DataDs16FileHead))
    {
        DataDs16FileHead *dhead = (DataDs16FileHead *)( m_embAbsData.data());
        dhead->beginX += left;
        dhead->beginY += front;
        dhead->maxX += left;
        dhead->minX += left;
        dhead->maxY += front;
        dhead->minY += front;
    }
}
//-----------------------------------------------------------------------

// 生成预览文件
int DataFileDst::createPreviewImage(QImage * pImg, int saveflag, int penwidth, int reDraw)
{
#if(1)
    if(reDraw == 0)//图片存在则不重画
    {
        // 图片是否存在，存在则返回
        QString previewPath = getFileFullPathName() + ".preview.png";
        QFile imageFile(previewPath);
        if (imageFile.exists())
        {
            return 0;
        }
    }
#endif

    int newimgflag = 0;
    QImage * pImage;
    int width, height;
    if (pImg == NULL)
    {
        width = DST_PREVIEW_WIDTH;
        height = DST_PREVIEW_HEIGHT;
        pImage = new QImage(width, height, IMAGE_TYPE);
        newimgflag = 1;
    }
    else
    {
        pImage = pImg;
    }

    width = pImage->width();
    height = pImage->height();
    if (width <= DST_PREVIEW_SIDE*2 || height <= DST_PREVIEW_SIDE*2)
    {
        if (pImage != NULL && newimgflag == 1)
        {
            delete pImage;
        }
        qDebug("preview img too small");
        return -1;
    }

    memset(pImage->bits(), 0x00, pImage->byteCount());

    QPainter painter(pImage);
    QColor backcolor(255, 255, 255, 0);         // 透明背景
    // 背景
    QPen pen;
    pen.setWidth(penwidth);
    pen.setColor(backcolor);
    painter.setPen(pen);
    painter.setBrush(backcolor);
    painter.drawRect(0, 0, width, height);

    // 图形
    //qDebug()<<"convertDataToAbs defore";
    convertDataToAbs();     // 转换为绝对坐标数据
    //qDebug()<<"convertDataToAbs end";

    // absdat数据
    int size = m_embAbsData.size();
    if (size <= (int)sizeof(DataDs16FileHead))
    {
        qDebug("2 data less then head size");
        return -1;
    }
    DataDs16FileHead * pAbsHead = (DataDs16FileHead *)(m_embAbsData.data());
    int datasize = size - sizeof(DataDs16FileHead);
    if (datasize <= 0)
    {
        qDebug("absdat dataBegin err");
        return -1;
    }
    int stepsize = datasize/sizeof(DsAbsItem);
    if (stepsize <= 0)
    {
        qDebug("absdat data size err");
        return -1;
    }
    DsAbsItem * pData = (DsAbsItem *)(m_embAbsData.data() + sizeof(DataDs16FileHead));
    DsAbsItem * absDataPtr = pData;
    //--------

    // 图形显示区域
    int dpminx = DST_PREVIEW_SIDE;
    int dpmaxx = width - DST_PREVIEW_SIDE;
    int dpminy = DST_PREVIEW_SIDE;
    int dpmaxy = height - DST_PREVIEW_SIDE;

    // 计算缩放系数
    double factor, temp;
    if ((dpmaxx - dpminx) <= 0 || (dpmaxy - dpminy) <= 0)
    {
        return -1;
    }

    factor = (double)(fabs(m_maxX - m_minX)) / (dpmaxx - dpminx);      // 按x计算的缩放系数
    temp =   (double)(fabs(m_maxY - m_minY)) / (dpmaxy - dpminy);      // 按x计算的缩放系数

    if (temp >= factor)     // 使用较大的缩放系数
    {
        factor = temp;
    }

    // 计算显示参数，按照图形的实际位置显示（数据坐标零点对应图形中心）
    int dpx = (int)((dpminx+dpmaxx)/2 - ((m_maxX+m_minX)/factor)/2);
    int dpy = (int)((dpminy+dpmaxy)/2 - ((m_maxY+m_minY)/factor)/2);

    // 显示花样图形
    u8 ctrlByte;
    int dx;
    int dy;

    double datposx, datposy;
    int curx, cury, prex, prey;

    datposx = pAbsHead->beginX;
    datposy = pAbsHead->beginY;

    curx = (datposx) / factor + dpx;
    cury = (datposy) / factor + dpy;

    if (DST_SHOWDIRX == -1)
    {
        curx = (width)-curx;
    }
    if (DST_SHOWDIRY == -1)
    {
        cury = (height)-cury;
    }

    absDataPtr = pData;

    QColor embcolor = QColor(Qt::green);
    pen.setColor(embcolor);
    painter.setPen(pen);

    for (int i = 0; i < stepsize; i++)
    {
        // 读入一个针步数据
        ctrlByte = absDataPtr->ctrl;

        if ( ctrlByte == DATA_SEWING  ||
             0 )
        {
            prex = curx;
            prey = cury;

            dx = absDataPtr->ax;
            dy = absDataPtr->ay;

            datposx = dx;
            datposy = dy;

            curx = (datposx) / factor + dpx;
            cury = (datposy) / factor + dpy;

            if (DST_SHOWDIRX == -1)
            {
                curx = (width)-curx;
            }
            if (DST_SHOWDIRY == -1)
            {
                cury = (height)-cury;
            }

            if(i != 0)
            {
                painter.drawLine(prex, prey, curx, cury);
            }
        }


        //如果连续两步都是跳针，则过滤掉
        else if (ctrlByte == DATA_OFFSET)
        {
            DsAbsItem * JumpAbsDataPtr = pData;
            JumpAbsDataPtr = absDataPtr - 1;
            u8 beforectrlByte = JumpAbsDataPtr->ctrl;

            JumpAbsDataPtr = absDataPtr + 2;
            u8 nextctrlByte = JumpAbsDataPtr->ctrl;

            prex = curx;
            prey = cury;

            dx = absDataPtr->ax;
            dy = absDataPtr->ay;

            datposx = dx;
            datposy = dy;

            curx = (datposx) / factor + dpx;
            cury = (datposy) / factor + dpy;

            if (DST_SHOWDIRX == -1)
            {
                curx = (width)-curx;
            }
            if (DST_SHOWDIRY == -1)
            {
                cury = (height)-cury;
            }

            pen.setColor(embcolor);
            painter.setPen(pen);

            if(beforectrlByte == DATA_OFFSET || nextctrlByte == DATA_OFFSET)
            {
                //该针上下两针都是跳针则不画线
            }
            else
            {
                if(i != 0)
                {
                    painter.drawLine(prex, prey, curx, cury);
                }
            }
        }

        absDataPtr++;
    }

    // 保存成文件
    QString preview = getFileFullPathName();
    if (saveflag != 0 && preview.isEmpty() == false)
    {
#if (1)
        preview += ".preview.png";
        pImage->save(preview, "png");
#endif
    }

    if (pImage != NULL && newimgflag == 1)
    {
        delete pImage;
    }

    return 0;
}

#define EMB_DST_DAT_DIRX    (-1)     // X向DST数据坐标和绝对数据坐标的差异
#define EMB_DST_DAT_DIRY    (1)      // Y向DST数据坐标和绝对数据坐标的差异

// 针步转换
int DataFileDst::changeDstStep(DstStep * pDststep, Ds4Item & ds4step)
{
    int dx, dy;
    u8 c1, c2, c3;
    u8 ctrl, attr;

    if (pDststep == NULL)
    {
        return -1;
    }

    c1 = pDststep->c1;
    c2 = pDststep->c2;
    c3 = pDststep->c3;

    dx = 0;
    dy = 0;

    if ((c1&0x08) != 0) {   dx -= 9;    }
    if ((c1&0x04) != 0) {   dx += 9;    }
    if ((c1&0x02) != 0) {   dx -= 1;    }
    if ((c1&0x01) != 0) {   dx += 1;    }
    if ((c2&0x08) != 0) {   dx -= 27;   }
    if ((c2&0x04) != 0) {   dx += 27;   }
    if ((c2&0x02) != 0) {   dx -= 3;    }
    if ((c2&0x01) != 0) {   dx += 3;    }
    if ((c3&0x08) != 0) {   dx -= 81;   }
    if ((c3&0x04) != 0) {   dx += 81;   }

    if ((c1&0x10) != 0) {   dy -= 9;    }
    if ((c1&0x20) != 0) {   dy += 9;    }
    if ((c1&0x40) != 0) {   dy -= 1;    }
    if ((c1&0x80) != 0) {   dy += 1;    }
    if ((c2&0x10) != 0) {   dy -= 27;   }
    if ((c2&0x20) != 0) {   dy += 27;   }
    if ((c2&0x40) != 0) {   dy -= 3;    }
    if ((c2&0x80) != 0) {   dy += 3;    }
    if ((c3&0x10) != 0) {   dy -= 81;   }
    if ((c3&0x20) != 0) {   dy += 81;   }

    if (c3 == 0xF3 && dx == 0 && dy == 0)
    {
        ctrl = DATA_END;            // 结束
    }
    else if ((c3&0xc3) == 0x03)     // 运针
    {
        ctrl = DATA_SEWING;
    }
    else if ((c3&0xc3) == 0x83)     // 偏移
    {
        ctrl = DATA_OFFSET;
    }
    else if ((c3&0xc3) == 0xC3)     // 换色
    {
        ctrl = DATA_CHGND;
    }
    else if ((c3&0xc3) == 0x43)     // 开关亮片码
    {
        qDebug("Sequin switch, not support, c1=0x%x, c2=0x%x, c3=0x%x", c1, c2, c3);   // 不合法的DST
        return -2;
    }
    else
    {
        qDebug("not know dst step, c1=0x%x, c2=0x%x, c3=0x%x", c1, c2, c3);   // 不合法的DST
        return -3;
    }

    // 添加针步
    attr = 0;

    dx *= EMB_DST_DAT_DIRX;      // X向显示坐标和数据坐标的差异
    dy *= EMB_DST_DAT_DIRY;      // Y向显示坐标和数据坐标的差异

    if (dx < 0) {   attr |= 0x80;   }
    if (dy < 0) {   attr |= 0x40;   }

    ds4step.ctrl = ctrl;
    ds4step.attr = attr;
    ds4step.dx = abs(dx);
    ds4step.dy = abs(dy);

    return 0;
}
